﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/// <summary>
/// https://zhuanlan.zhihu.com/p/137786467 
/// </summary>
public class TransformationGrid : MonoBehaviour
{

    public Transform prefab;

    public int gridResolution = 10;

    private Transform[] grid;
    private List<Transformation> transformations;
    private Matrix4x4 transformation;

    void Awake()
    {
        grid = new Transform[gridResolution * gridResolution * gridResolution];
        for (int i = 0, z = 0; z < gridResolution; z++)
        {
            for (int y = 0; y < gridResolution; y++)
            {
                for (int x = 0; x < gridResolution; x++, i++)
                {
                    grid[i] = CreateGridPoint(x, y, z);
                }
            }
        }

        transformations = new List<Transformation>();
    }

    void Update()
    {
        UpdateTransformation();
        for (int i=0, z=0; z<gridResolution; z++)
        {
            for (int y=0; y<gridResolution; y++)
            {
                for (int x=0; x<gridResolution; x++, i++)
                {
                    grid[i].localPosition = TransformPoint(x, y, z);
                }
            }
        }
    }

    void UpdateTransformation()
    {
        GetComponents(transformations);
        if (transformations.Count > 0)
        {
            transformation = transformations[0].Matrix;
            for (int i=1; i<transformations.Count; i++)
            {
                transformation = transformations[i].Matrix * transformation;
            }
        }
    }

    Transform CreateGridPoint(int x, int y, int z)
    {
        Transform point = Instantiate(prefab);
        point.localPosition = GetCoordinates(x, y, z);
        point.parent = transform;
        point.GetComponent<MeshRenderer>().material.color = new Color(
                (float)x / gridResolution,
                (float)y / gridResolution,
                (float)z / gridResolution
            );
        return point;
    }
    
    Vector3 GetCoordinates(int x, int y, int z)
    {
        return new Vector3(
            x - (gridResolution -1) * prefab.localScale.x,
            y - (gridResolution - 1) * prefab.localScale.y,
            z - (gridResolution - 1) * prefab.localScale.z
            );
    }

    Vector3 TransformPoint(int x, int y, int z)
    {
        Vector3 coordinates = GetCoordinates(x, y, z);
        //for (int i = 0; i < transformations.Count; i++)
        //{
        //    coordinates = transformations[i].Apply(coordinates);
        //}
        //return coordinates;
        return transformation.MultiplyPoint(coordinates);
    }

}
